#include "AudioOutput.h"
#include <QDebug>

extern "C" {
    #include <libavutil/frame.h>
}


AudioOutput::AudioOutput(QObject* parent)
:QObject(parent)
,m_deviceId(0)
,m_swrContext(nullptr)
,m_currentFramePos(0)
,m_volume(100)
,m_isInitialized(false)
,m_isPlaying(false)
,m_shouldStop(false)
,m_totalPlayedSamples(0)
,m_startTimeMs(0)
,m_playbackSpeed(1.0)
{
    qDebug() << "[AudioOutput] 创建音频输出";
}


AudioOutput::~AudioOutput()
{
    stop();
    if (m_deviceId > 0) {
        SDL_CloseAudioDevice(m_deviceId);
        m_deviceId = 0;
    }
    
    qDebug() << "[AudioOutput] 销毁音频输出";

}

bool AudioOutput::init(int sampleRate, int channels, SwrContext* swrContext)
{
    if (m_isInitialized) {
        qDebug() << "[AudioOutput] 已经初始化，先关闭";
        stop();
        
        if (m_deviceId > 0) {
            SDL_CloseAudioDevice(m_deviceId);
            m_deviceId = 0;
        }
        
        // 重置所有状态
        m_isInitialized = false;
        m_isPlaying = false;
    }

    m_swrContext = swrContext;
    
    // 初始化SDL音频子系统
    if (SDL_Init(SDL_INIT_AUDIO) < 0) {
        qDebug() << "[AudioOutput] 初始化SDL失败：" << SDL_GetError();
        return false;
    }

    // 设置期望的音频格式
    SDL_AudioSpec desired;
    SDL_zero(desired);
    desired.freq = sampleRate;
    desired.format = AUDIO_S16SYS;      // 16位有符号整数
    desired.channels = channels;
    desired.samples = 1024;             // 缓冲大小
    desired.callback = audioCallback;   // 回调函数
    desired.userdata = this;            // 传递this指针

    // 打开音频设备
    m_deviceId = SDL_OpenAudioDevice(nullptr, 0, &desired, &m_audioSpec, 0);
    if (m_deviceId == 0) {
        qDebug() << "[AudioOutput] 打开音频设备失败：" << SDL_GetError();
        SDL_Quit();
        return false;
    }
    
    m_isInitialized = true;

    qDebug() << "[AudioOutput] 初始化成功";
    qDebug() << "  采样率：" << m_audioSpec.freq << "Hz";
    qDebug() << "  声道数：" << (int)m_audioSpec.channels;
    qDebug() << "  缓冲大小：" << m_audioSpec.samples << "样本";
   
    return true;
}


void AudioOutput::play()
{
    if (!m_isInitialized) {
        qDebug() << "[AudioOutput] 未初始化，无法播放";
        return;
    }
    
    if (m_isPlaying) {
        qDebug() << "[AudioOutput] 已经在播放";
        return;
    }
    
    // 🔧 重置停止标志，允许接受新帧
    {
        QMutexLocker locker(&m_mutex);
        m_shouldStop = false;
    }
    
    // 如果是第一次播放或从头开始，重置时间跟踪
    if (m_totalPlayedSamples == 0) {
        m_startTimeMs = 0;
    }
    
    SDL_PauseAudioDevice(m_deviceId, 0);  // 0 = 播放，1 = 暂停
    m_isPlaying = true;
    
    emit playbackResumed();
    qDebug() << "[AudioOutput] 开始播放";
}


void AudioOutput::pause()
{
    if (!m_isPlaying || !m_isInitialized || m_deviceId == 0) return;
    
    qDebug() << "[AudioOutput] pause: 暂停音频设备";
    SDL_PauseAudioDevice(m_deviceId, 1);  // 暂停
    
    // 使用 SDL_LockAudioDevice 确保回调完全停止
    qDebug() << "[AudioOutput] pause: 锁定设备，等待回调停止";
    SDL_LockAudioDevice(m_deviceId);
    m_isPlaying = false;
    SDL_UnlockAudioDevice(m_deviceId);
    
    qDebug() << "[AudioOutput] pause: 完成";
    emit playbackPaused();
}

void AudioOutput::stop()
{
    if (!m_isInitialized || m_deviceId == 0) return;
    
    SDL_PauseAudioDevice(m_deviceId, 1);  // 先暂停SDL2设备
    
    // 锁定SDL2设备，确保音频回调完全停止（释放 m_mutex）
    SDL_LockAudioDevice(m_deviceId);
    m_isPlaying = false;
    SDL_UnlockAudioDevice(m_deviceId);
    
    // 设置停止标志并清空缓冲区
    {
        QMutexLocker locker(&m_mutex);
        m_shouldStop = true;
        m_condition.wakeAll();  // 唤醒所有等待的 pushFrame()
    }
    
    clearBuffer();
}

void AudioOutput::setVolume(int volume)
{
    m_volume = qBound(0, volume, 100);
    qDebug() << "[AudioOutput] 设置音量：" << m_volume;
}

int AudioOutput::getVolume() const
{
    return m_volume;
}


void AudioOutput::pushFrame(AudioFrame frame)
{
    QMutexLocker locker(&m_mutex);
    
    // 🔧 如果已经停止，立即返回，不再接受新帧
    if (m_shouldStop) {
        qDebug() << "[AudioOutput] 已停止，拒绝新帧";
        return;
    }
    
    // 如果队列满了，等待
    while (m_frameQueue.size() >= MAX_BUFFER_SIZE && !m_shouldStop) {
        qDebug() << "[AudioOutput] 队列已满，等待...";
        m_condition.wait(&m_mutex, 100);  // 最多等待100ms
        
        // 再次检查停止标志
        if (m_shouldStop) {
            qDebug() << "[AudioOutput] 等待时收到停止信号，退出";
            return;
        }
        
        if (m_frameQueue.size() >= MAX_BUFFER_SIZE) {
            qDebug() << "[AudioOutput] 队列仍然满，丢弃旧帧";
            m_frameQueue.pop();  // std::queue 用 pop() 删除队首元素
        }
    }
    
    // 再次检查停止标志（防止在循环后被停止）
    if (m_shouldStop) {
        qDebug() << "[AudioOutput] 推送前收到停止信号，退出";
        return;
    }
    
    m_frameQueue.push(std::move(frame));  // std::queue 用 push() 添加元素
    m_condition.wakeOne();
}

void AudioOutput::clearBuffer()
{
    QMutexLocker locker(&m_mutex);
    
    qDebug() << "[AudioOutput] clearBuffer: 开始清空队列";
    
    // 清空队列
    while (!m_frameQueue.empty()) {
        m_frameQueue.pop();
    }
    
    m_currentFrame.release();
    m_currentFramePos = 0;
    
    // 重置时间跟踪（用于 seek 跳转）
    m_totalPlayedSamples = 0;
    m_startTimeMs = 0;
    
    // 🔧 唤醒所有可能在 pushFrame() 中等待的线程
    m_condition.wakeAll();
    
    qDebug() << "[AudioOutput] clearBuffer: 完成";
}


int AudioOutput::getBufferSize() const
{
    QMutexLocker locker(&m_mutex);
    return m_frameQueue.size();
}

bool AudioOutput::isBufferFull() const
{
    QMutexLocker locker(&m_mutex);
    return m_frameQueue.size() >= MAX_BUFFER_SIZE;
}

int64_t AudioOutput::getCurrentTimeMs() const
{
    QMutexLocker locker(&m_mutex);
    
    if (!m_isInitialized || m_audioSpec.freq == 0) {
        return 0;
    }
    
    // 根据已播放的样本数计算当前时间
    // 🎯 关键：需要乘以倍速来得到逻辑时间
    // 例如：2倍速时，SDL2采样率是22050，但逻辑时间应该是原速的2倍
    // 物理播放 1 秒（22050样本）→ 逻辑时间 2 秒
    int64_t playedMs = (m_totalPlayedSamples * 1000) / m_audioSpec.freq;
    int64_t logicalTimeMs = static_cast<int64_t>(playedMs * m_playbackSpeed);
    return m_startTimeMs + logicalTimeMs;
}

void AudioOutput::setPlaybackSpeed(double speed)
{
    QMutexLocker locker(&m_mutex);
    m_playbackSpeed = speed;
    qDebug() << "[AudioOutput] 设置播放倍速：" << speed << "x（用于时间计算）";
}

void AudioOutput::audioCallback(void* userdata, Uint8* stream, int len)
{
    AudioOutput* output = static_cast<AudioOutput*>(userdata);
    output->fillAudioBuffer(stream, len);
}

void AudioOutput::fillAudioBuffer(Uint8* stream, int len)
{
    //清零输出缓冲区
    SDL_memset(stream, 0, len);
    QMutexLocker locker(&m_mutex);

    int remainingLen = len;
    Uint8* streamPtr = stream;

    while(remainingLen > 0)
    {
        if(!m_currentFrame.isValid()||m_currentFramePos>=m_currentFrame.getNbSamples())
        {
            if(m_frameQueue.empty())  // std::queue 用 empty() 检查是否为空
            {
                break;
            }

            // std::queue 需要先 front() 获取元素，再 pop() 删除
            m_currentFrame = std::move(m_frameQueue.front());
            m_frameQueue.pop();
            m_currentFramePos=0;
            
            // 如果是第一帧，记录起始时间
            if (m_totalPlayedSamples == 0 && m_currentFrame.isValid()) {
                m_startTimeMs = m_currentFrame.getPtsMs();
            }
            
            m_condition.wakeOne();
        }

        if(!m_currentFrame.isValid())
        {
            break;
        }

          // 重采样音频数据
          uint8_t* outputBuffer = nullptr;
          int outputSamples = 0;
          
          AVFrame* rawFrame = m_currentFrame.getRawFrame();
          
          // 计算剩余可用的样本数
          int availableSamples = m_currentFrame.getNbSamples() - m_currentFramePos;
          int samplesNeeded = remainingLen / (2 * m_audioSpec.channels); // 2字节 * 声道数
          int samplesToConvert = qMin(availableSamples, samplesNeeded);
          
          // 创建临时输出缓冲区
          av_samples_alloc(&outputBuffer, nullptr, m_audioSpec.channels,
                          samplesToConvert, AV_SAMPLE_FMT_S16, 0);
          
          // 调整输入指针到当前位置
          const uint8_t* inputData[AV_NUM_DATA_POINTERS] = {nullptr};
          for (int i = 0; i < AV_NUM_DATA_POINTERS; i++) {
              if (rawFrame->data[i]) {
                  int bytesPerSample = av_get_bytes_per_sample((AVSampleFormat)rawFrame->format);
                  inputData[i] = rawFrame->data[i] + m_currentFramePos * bytesPerSample;
              }
          }
          
          // 执行重采样
          outputSamples = swr_convert(m_swrContext, &outputBuffer, samplesToConvert,
                                     inputData, samplesToConvert);
          
          if (outputSamples > 0) {
              int dataSize = outputSamples * 2 * m_audioSpec.channels;  // 2字节 * 声道数
              int copySize = qMin(dataSize, remainingLen);
              
              // 应用音量
              if (m_volume < 100) {
                  for (int i = 0; i < copySize / 2; i++) {
                      int16_t* sample = (int16_t*)(outputBuffer + i * 2);
                      *sample = (*sample * m_volume) / 100;
                  }
              }
              
              // 混音到输出流
              SDL_MixAudioFormat(streamPtr, outputBuffer, m_audioSpec.format, copySize, SDL_MIX_MAXVOLUME);
              
              streamPtr += copySize;
              remainingLen -= copySize;
              m_currentFramePos += outputSamples;
              
              // 累计已播放的样本数（用于音视频同步）
              m_totalPlayedSamples += outputSamples;
          }
          
          // 释放临时缓冲区
          av_freep(&outputBuffer);

    }
}
